<!DOCTYPE html>
<html lang="zh">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>正弦数组生成</title>
    <style>
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background-color: #f4f4f9;
            margin: 0;
            padding: 20px;
            display: flex;
            flex-direction: column;
            align-items: center;
        }

        h1 {
            color: #333;
            margin-bottom: 20px;
        }

        .input-group {
            display: flex;
            flex-wrap: wrap;
            gap: 10px;
            margin-bottom: 20px;
            justify-content: center;
        }

        .input-group label {
            display: flex;
            align-items: center;
            gap: 5px;
        }

        .input-group input,
        .input-group button {
            padding: 8px 12px;
            border: 1px solid #ccc;
            border-radius: 4px;
            font-size: 14px;
        }

        .input-group button {
            background-color: #007BFF;
            color: white;
            cursor: pointer;
            transition: background-color 0.3s ease;
        }

        .input-group button:hover {
            background-color: #0056b3;
        }

        #result {
            width: 100%;
            max-width: 800px;
            max-height: 200px;
            overflow-y: auto;
            white-space: pre-wrap;
            background-color: white;
            border: 1px solid #ccc;
            border-radius: 4px;
            padding: 10px;
            margin-bottom: 20px;
        }

        #functionDisplay {
            width: 100%;
            max-width: 800px;
            font-family: 'Courier New', Courier, monospace;
            font-size: 18px;
            color: #333;
            font-weight: bold;
            text-align: center;
            background-color: #e9ecef;
            border: 1px solid #ccc;
            border-radius: 4px;
            padding: 10px;
            margin-bottom: 20px;
        }

        canvas {
            width: 100%;
            max-width: 800px;
            border: 1px solid #ccc;
            border-radius: 4px;
            background-color: white;
        }
    </style>
</head>

<body>
    <h1>正弦数组生成</h1>
    <div class="input-group">
        <label for="arraySize">数组大小:</label>
        <input type="number" id="arraySize" value="100" min="1">
        <label for="halfCycle">半周模式:</label>
        <input type="checkbox" id="halfCycle">
        <label for="amplitude">正弦幅度:</label>
        <input type="number" id="amplitude" value="1" min="0">
        <label for="precision">精度:</label>
        <input type="number" id="precision" value="2" min="0">
        <label for="hexMode">十六进制显示:</label>
        <input type="checkbox" id="hexMode">
        <label for="q131Mode">Q1.31 format 格式:</label>
        <input type="checkbox" id="q131Mode">
        <label for="midValue">中值数:</label>
        <input type="number" id="midValue" value="0">
        <button onclick="generateAndDisplaySineArray()">生成</button>
        <button onclick="saveSineArray()">保存数组</button>
        <input type="file" id="fileInput" accept=".json" onchange="loadSineArray(event)">
    </div>
    <div id="result"></div>
    <div id="functionDisplay"></div>
    <canvas id="waveform" width="800" height="200"></canvas>

    <script>
        const PI = Math.PI;

        function generateSineArray(size, isHalfCycle, amplitude, midValue) {
            const sineArray = [];
            const cycleRange = isHalfCycle ? PI : 2 * PI;
            for (let i = 0; i < size; i++) {
                const angle = cycleRange * i / size;
                sineArray.push(midValue + amplitude * Math.sin(angle));
            }
            return sineArray;
        }

        function drawWaveform(sineArray) {
            const canvas = document.getElementById('waveform');
            const ctx = canvas.getContext('2d');
            ctx.clearRect(0, 0, canvas.width, canvas.height);

            // 绘制网格线
            ctx.strokeStyle = '#ccc';
            ctx.lineWidth = 1;
            const gridStepX = 50;
            const gridStepY = 50;
            for (let x = 0; x < canvas.width; x += gridStepX) {
                ctx.beginPath();
                ctx.moveTo(x, 0);
                ctx.lineTo(x, canvas.height);
                ctx.stroke();
            }
            for (let y = 0; y < canvas.height; y += gridStepY) {
                ctx.beginPath();
                ctx.moveTo(0, y);
                ctx.lineTo(canvas.width, y);
                ctx.stroke();
            }

            const scaleX = canvas.width / sineArray.length;
            const maxValue = Math.max(...sineArray.map(Math.abs));
            const scaleY = canvas.height / (2 * maxValue);
            const offsetY = canvas.height / 2;

            ctx.beginPath();
            ctx.moveTo(0, offsetY - sineArray[0] * scaleY);
            for (let i = 1; i < sineArray.length; i++) {
                ctx.lineTo(i * scaleX, offsetY - sineArray[i] * scaleY);
            }
            ctx.strokeStyle = 'blue';
            ctx.lineWidth = 2;
            ctx.stroke();
        }

        function floatToQ131(floatValue) {
            const maxValue = (1 << 31) - 1;
            const scaledValue = Math.round(floatValue * maxValue);
            return scaledValue & 0xFFFFFFFF;
        }

        function formatValue(value, precision, isHex, isQ131) {
            if (isQ131) {
                const q131Value = floatToQ131(value);
                return q131Value.toString(16).padStart(8, '0');
            }
            if (isHex) {
                return Math.round(value).toString(16);
            }
            return value.toFixed(precision);
        }

        function generateAndDisplaySineArray() {
            const arraySizeInput = document.getElementById('arraySize');
            const arraySize = parseInt(arraySizeInput.value);
            if (isNaN(arraySize) || arraySize < 1) {
                alert('请输入有效的正整数作为数组大小。');
                return;
            }
            const isHalfCycle = document.getElementById('halfCycle').checked;
            const amplitudeInput = document.getElementById('amplitude');
            const amplitude = parseFloat(amplitudeInput.value);
            if (isNaN(amplitude) || amplitude < 0) {
                alert('请输入有效的非负幅度值。');
                return;
            }
            const precisionInput = document.getElementById('precision');
            const precision = parseInt(precisionInput.value);
            if (isNaN(precision) || precision < 0) {
                alert('请输入有效的非负精度值。');
                return;
            }
            const isHex = document.getElementById('hexMode').checked;
            const isQ131 = document.getElementById('q131Mode').checked;
            const midValueInput = document.getElementById('midValue');
            const midValue = parseFloat(midValueInput.value);

            const sineArray = generateSineArray(arraySize, isHalfCycle, amplitude, midValue);
            const resultDiv = document.getElementById('result');
            let resultText = '[';
            const maxLineLength = 80;
            let currentLineLength = 0;
            sineArray.forEach((value, index) => {
                const formattedValue = formatValue(value, precision, isHex, isQ131);
                const valueLength = formattedValue.length;
                if (currentLineLength + valueLength + 2 > maxLineLength) {
                    resultText += '\n';
                    currentLineLength = 0;
                }
                resultText += formattedValue;
                if (index < sineArray.length - 1) {
                    resultText += ', ';
                    currentLineLength += valueLength + 2;
                }
            });
            resultText += ']';
            resultDiv.innerHTML = `<p>生成的正弦数组内容如下:</p><pre>${resultText}</pre>`;

            drawWaveform(sineArray);

            const functionDisplayDiv = document.getElementById('functionDisplay');
            const functionText = `f(x) = ${midValue} + ${amplitude} * sin(x)`;
            functionDisplayDiv.innerHTML = `<p>设置后的正弦函数为: ${functionText}</p>`;
        }

        function saveSineArray() {
            const arraySize = parseInt(document.getElementById('arraySize').value);
            const isHalfCycle = document.getElementById('halfCycle').checked;
            const amplitude = parseFloat(document.getElementById('amplitude').value);
            const precision = parseInt(document.getElementById('precision').value);
            const isHex = document.getElementById('hexMode').checked;
            const isQ131 = document.getElementById('q131Mode').checked;
            const midValue = parseFloat(document.getElementById('midValue').value);

            const sineArray = generateSineArray(arraySize, isHalfCycle, amplitude, midValue);
            const data = {
                arraySize,
                isHalfCycle,
                amplitude,
                precision,
                isHex,
                isQ131,
                midValue,
                sineArray
            };
            const jsonData = JSON.stringify(data);
            const blob = new Blob([jsonData], { type: 'application/json' });
            const url = URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = 'sine_array.json';
            a.click();
            URL.revokeObjectURL(url);
        }

        function loadSineArray(event) {
            const file = event.target.files[0];
            if (file) {
                const reader = new FileReader();
                reader.onload = function (e) {
                    const data = JSON.parse(e.target.result);
                    document.getElementById('arraySize').value = data.arraySize;
                    document.getElementById('halfCycle').checked = data.isHalfCycle;
                    document.getElementById('amplitude').value = data.amplitude;
                    document.getElementById('precision').value = data.precision;
                    document.getElementById('hexMode').checked = data.isHex;
                    document.getElementById('q131Mode').checked = data.isQ131;
                    document.getElementById('midValue').value = data.midValue;

                    const resultDiv = document.getElementById('result');
                    let resultText = '[';
                    const maxLineLength = 80;
                    let currentLineLength = 0;
                    data.sineArray.forEach((value, index) => {
                        const formattedValue = formatValue(value, data.precision, data.isHex, data.isQ131);
                        const valueLength = formattedValue.length;
                        if (currentLineLength + valueLength + 2 > maxLineLength) {
                            resultText += '\n';
                            currentLineLength = 0;
                        }
                        resultText += formattedValue;
                        if (index < data.sineArray.length - 1) {
                            resultText += ', ';
                            currentLineLength += valueLength + 2;
                        }
                    });
                    resultText += ']';
                    resultDiv.innerHTML = `<p>加载的正弦数组内容如下:</p><pre>${resultText}</pre>`;

                    drawWaveform(data.sineArray);

                    const functionDisplayDiv = document.getElementById('functionDisplay');
                    const functionText = `f(x) = ${data.midValue} + ${data.amplitude} * sin(x)`;
                    functionDisplayDiv.innerHTML = `<p>设置后的正弦函数为: ${functionText}</p>`;
                };
                reader.readAsText(file);
            }
        }
    </script>
</body>

</html>    